<template>
  <div id="app">
    <button @click="returnFn" class="btn btn-primary retrunBUtton">
      <i class="icon">⚡</i> 返回
    </button>
    <div class="container">
      <header>
        <h1>正则表达式在线测试工具</h1>
        <p class="subtitle">实时测试正则表达式，支持多种匹配模式</p>
      </header>

      <div class="main-content">
        <!-- 正则表达式输入区域 -->
        <div class="regex-section">
          <div class="section-title">
            <h2>正则表达式</h2>
            <div class="button-group">
              <button @click="insertCommonPattern" class="btn btn-secondary">
                <i class="icon">📋</i> 常用模式
              </button>
              <button @click="clearRegex" class="btn btn-secondary">
                <i class="icon">🗑️</i> 清空
              </button>
            </div>
          </div>

          <div class="regex-input-container">
            <div class="regex-prefix">/</div>
            <input
              type="text"
              v-model="regexPattern"
              placeholder="输入正则表达式，如：^[a-zA-Z0-9]+$"
              class="regex-input"
              :class="{ error: regexError }"
              @input="testRegex"
            />
            <div class="regex-suffix">/{{ flags }}</div>
          </div>

          <!-- 标志位选择 -->
          <div class="flags-section">
            <h3>匹配模式</h3>
            <div class="flags-grid">
              <label v-for="flag in availableFlags" :key="flag.value" class="flag-checkbox">
                <input
                  type="checkbox"
                  :value="flag.value"
                  v-model="selectedFlags"
                  class="flag-input"
                />
                <span class="flag-label">
                  <span class="flag-char">{{ flag.value }}</span>
                  <span class="flag-desc">{{ flag.description }}</span>
                </span>
              </label>
            </div>
          </div>

          <div v-if="regexError" class="error-message"><i class="icon">❌</i> {{ regexError }}</div>
        </div>

        <!-- 测试文本区域 -->
        <div class="test-section">
          <div class="section-title">
            <h2>测试文本</h2>
            <div class="button-group">
              <button @click="insertSampleText" class="btn btn-secondary">
                <i class="icon">📄</i> 示例文本
              </button>
              <button @click="clearTestText" class="btn btn-secondary">
                <i class="icon">🗑️</i> 清空
              </button>
            </div>
          </div>

          <textarea
            v-model="testText"
            placeholder="输入要测试的文本内容"
            class="test-textarea"
            @input="testRegex"
          ></textarea>
        </div>

        <!-- 匹配结果 -->
        <div class="results-section">
          <div class="section-title">
            <h2>匹配结果</h2>
            <div class="button-group">
              <button @click="copyResults" class="btn btn-success" :disabled="!hasMatches">
                <i class="icon">📋</i> {{ copyButtonText }}
              </button>
              <button @click="exportResults" class="btn btn-primary" :disabled="!hasMatches">
                <i class="icon">💾</i> 导出结果
              </button>
            </div>
          </div>

          <div class="results-container">
            <!-- 匹配统计 -->
            <div class="stats-card">
              <div class="stat-item">
                <span class="stat-label">匹配数量</span>
                <span class="stat-value">{{ matchCount }}</span>
              </div>
              <div class="stat-item">
                <span class="stat-label">匹配模式</span>
                <span class="stat-value">{{ flags }}</span>
              </div>
              <div class="stat-item">
                <span class="stat-label">测试状态</span>
                <span class="stat-value" :class="regexError ? 'error' : 'success'">
                  {{ regexError ? '错误' : '正常' }}
                </span>
              </div>
            </div>

            <!-- 匹配详情 -->
            <div class="matches-container" v-if="hasMatches">
              <h3>匹配详情</h3>
              <div class="matches-list">
                <div v-for="(match, index) in matches" :key="index" class="match-item">
                  <div class="match-header">
                    <span class="match-index">#{{ index + 1 }}</span>
                    <span class="match-position"
                      >位置: {{ match.index }} - {{ match.index + match.text.length }}</span
                    >
                    <span class="match-length">长度: {{ match.text.length }}</span>
                  </div>
                  <div class="match-content">{{ match.text }}</div>

                  <!-- 分组信息 -->
                  <div v-if="match.groups && match.groups.length > 0" class="match-groups">
                    <div
                      v-for="(group, groupIndex) in match.groups"
                      :key="groupIndex"
                      class="group-item"
                    >
                      <span class="group-name">分组{{ groupIndex }}</span>
                      <span class="group-content">{{ group }}</span>
                    </div>
                  </div>
                </div>
              </div>
            </div>

            <!-- 无匹配结果 -->
            <div v-else-if="regexPattern && testText && !regexError" class="no-matches">
              <i class="icon">🔍</i>
              <p>未找到匹配项</p>
            </div>

            <!-- 高亮显示匹配文本 -->
            <div v-if="!regexError && testText" class="highlight-container">
              <h3>文本高亮</h3>
              <div class="highlighted-text" v-html="highlightedText"></div>
            </div>
          </div>
        </div>

        <!-- 常用正则表达式库 -->
        <div class="patterns-library">
          <div class="section-title">
            <h2>常用正则表达式</h2>
            <button @click="showPatterns = !showPatterns" class="btn btn-secondary">
              <i class="icon">{{ showPatterns ? '📕' : '📚' }}</i>
              {{ showPatterns ? '收起' : '展开' }}
            </button>
          </div>

          <div v-if="showPatterns" class="patterns-grid">
            <div
              v-for="pattern in commonPatterns"
              :key="pattern.name"
              class="pattern-card"
              @click="applyPattern(pattern)"
            >
              <div class="pattern-name">{{ pattern.name }}</div>
              <div class="pattern-regex">{{ pattern.pattern }}</div>
              <div class="pattern-desc">{{ pattern.description }}</div>
            </div>
          </div>
        </div>
      </div>

      <footer>
        <p>正则表达式测试工具 v1.0 | 使用Vue 3开发</p>
      </footer>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'

// 响应式数据
const regexPattern = ref('')
const testText = ref('')
const selectedFlags = ref(['g'])
const regexError = ref('')
const copyButtonText = ref('复制结果')
const showPatterns = ref(false)
import { useRouter } from 'vue-router'
// 匹配结果
const matches = ref([])
const Router = useRouter()
// 可用标志位
const availableFlags = ref([
  { value: 'g', description: '全局匹配' },
  { value: 'i', description: '忽略大小写' },
  { value: 'm', description: '多行匹配' },
  { value: 's', description: '允许.匹配换行符' },
  { value: 'u', description: 'Unicode模式' },
  { value: 'y', description: '粘性匹配' }
])

// 常用正则表达式模式
const commonPatterns = ref([
  {
    name: '邮箱地址',
    pattern: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$',
    description: '匹配常见的电子邮件地址格式'
  },
  {
    name: '手机号码',
    pattern: '^1[3-9]\\d{9}$',
    description: '匹配中国大陆手机号码'
  },
  {
    name: '身份证号',
    pattern: '^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$',
    description: '匹配18位身份证号码'
  },
  {
    name: 'URL地址',
    pattern: '^https?:\\/\\/(?:www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_\\+.~#?&\\/=]*)$',
    description: '匹配HTTP/HTTPS网址'
  },
  {
    name: 'IP地址',
    pattern: '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$',
    description: '匹配IPv4地址'
  },
  {
    name: '中文汉字',
    pattern: '^[\\u4e00-\\u9fa5]+$',
    description: '匹配中文字符'
  },
  {
    name: '数字',
    pattern: '^-?\\d+(\\.\\d+)?$',
    description: '匹配整数或浮点数'
  },
  {
    name: 'HTML标签',
    pattern: '<([a-z][a-z0-9]*)[^>]*?(?:\\/>|>.*?<\\/\\1>)',
    description: '匹配HTML标签'
  }
])
const returnFn = () => {
  Router.go(-1)
}
// 计算属性
const flags = computed(() => selectedFlags.value.join(''))

const hasMatches = computed(() => matches.value.length > 0)

const matchCount = computed(() => matches.value.length)

const highlightedText = computed(() => {
  if (!testText.value || regexError.value || !regexPattern.value) {
    return testText.value
  }

  try {
    const regex = new RegExp(regexPattern.value, flags.value)
    return testText.value.replace(regex, (match) => {
      return `<mark class="highlight">${match}</mark>`
    })
  } catch (error) {
    return testText.value
  }
})

// 监听器
watch(selectedFlags, () => {
  if (regexPattern.value && testText.value) {
    testRegex()
  }
})

// 方法
const testRegex = () => {
  if (!regexPattern.value.trim()) {
    matches.value = []
    regexError.value = ''
    return
  }

  if (!testText.value.trim()) {
    matches.value = []
    regexError.value = ''
    return
  }

  try {
    // 测试正则表达式是否有效
    new RegExp(regexPattern.value, flags.value)
    regexError.value = ''

    // 执行匹配
    const regex = new RegExp(regexPattern.value, flags.value + 'g')
    const allMatches = []
    let match

    // 重置lastIndex以确保从开头开始匹配
    regex.lastIndex = 0

    while ((match = regex.exec(testText.value)) !== null) {
      const groups = match.slice(1).filter(group => group !== undefined)
      allMatches.push({
        index: match.index,
        text: match[0],
        groups: groups.length > 0 ? groups : null
      })

      // 避免无限循环
      if (match.index === regex.lastIndex) {
        regex.lastIndex++
      }
    }

    matches.value = allMatches
  } catch (error) {
    regexError.value = error.message
    matches.value = []
  }
}

const clearRegex = () => {
  regexPattern.value = ''
  regexError.value = ''
  matches.value = []
}

const clearTestText = () => {
  testText.value = ''
  matches.value = []
}

const insertCommonPattern = () => {
  regexPattern.value = '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'
  testText.value = '请联系我们：admin@example.com 或 support@test.org'
  testRegex()
}

const insertSampleText = () => {
  testText.value = `示例文本包含多种信息：
- 邮箱地址：user@domain.com
- 手机号码：13800138000
- 身份证号：110101199001011234
- 网址：https://www.example.com/path?query=1
- IP地址：192.168.1.1`

  if (regexPattern.value) {
    testRegex()
  }
}

const applyPattern = (pattern) => {
  regexPattern.value = pattern.pattern
  if (testText.value) {
    testRegex()
  }
}

const copyResults = async () => {
  if (!hasMatches.value) return

  const resultText = `正则表达式: /${regexPattern.value}/${flags.value}
测试文本: ${testText.value}
匹配数量: ${matchCount.value}

匹配结果:
${matches.value.map((match, index) =>
    `#${index + 1} 位置:${match.index}-${match.index + match.text.length} 内容:"${match.text}"`
  ).join('\n')}`

  try {
    await navigator.clipboard.writeText(resultText)
    copyButtonText.value = '已复制!'
    setTimeout(() => {
      copyButtonText.value = '复制结果'
    }, 2000)
  } catch (err) {
    console.error('复制失败: ', err)
    copyButtonText.value = '复制失败'
    setTimeout(() => {
      copyButtonText.value = '复制结果'
    }, 2000)
  }
}

const exportResults = () => {
  if (!hasMatches.value) return

  const resultData = {
    regex: `/${regexPattern.value}/${flags.value}`,
    testText: testText.value,
    matches: matches.value,
    timestamp: new Date().toISOString()
  }

  const dataStr = JSON.stringify(resultData, null, 2)
  const dataBlob = new Blob([dataStr], { type: 'application/json' })

  const link = document.createElement('a')
  link.href = URL.createObjectURL(dataBlob)
  link.download = `regex-results-${new Date().getTime()}.json`
  link.click()
  URL.revokeObjectURL(link.href)
}

// 初始化示例
insertCommonPattern()
</script>

<style scoped>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

#app {
  min-height: 100vh;
  background: linear-gradient(135deg, #8e2de2 0%, #4a00e0 100%);
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 20px;
  position: relative;
}
.retrunBUtton {
  position: absolute;
  top: 100px;
  right: 100px;
}

.container {
  width: 100%;
  max-width: 1300px;
  background-color: rgba(255, 255, 255, 0.95);
  border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
  overflow: hidden;
}

header {
  background: linear-gradient(to right, #8e2de2, #4a00e0);
  color: white;
  padding: 20px 30px;
  text-align: center;
}

h1 {
  font-size: 36px;
  margin-bottom: 5px;
}

.subtitle {
  font-size: 20px;
  opacity: 0.9;
}

.main-content {
  display: flex;
  flex-direction: column;
  padding: 25px;
  gap: 25px;
}

.section-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 15px;
  padding-bottom: 10px;
  border-bottom: 1px solid #eee;
}

.section-title h2 {
  font-size: 28px;
  color: #333;
}

.button-group {
  display: flex;
  gap: 10px;
}

.btn {
  padding: 8px 15px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 20px;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 5px;
  transition: all 0.3s ease;
}

.btn-primary {
  background: linear-gradient(to right, #8e2de2, #4a00e0);
  color: white;
}

.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(142, 45, 226, 0.3);
}

.btn-secondary {
  background: #f0f0f0;
  color: #333;
}

.btn-secondary:hover {
  background: #e0e0e0;
}

.btn-success {
  background: linear-gradient(to right, #00b09b, #96c93d);
  color: white;
}

.btn-success:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 176, 155, 0.3);
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none !important;
}

/* 正则表达式输入样式 */
.regex-input-container {
  display: flex;
  align-items: center;
  margin-bottom: 15px;
}

.regex-prefix,
.regex-suffix {
  padding: 10px;
  background: #f5f5f5;
  border: 1px solid #ddd;
  font-family: 'Courier New', monospace;
  font-size: 20px;
}

.regex-prefix {
  border-right: none;
  border-radius: 6px 0 0 6px;
}

.regex-suffix {
  border-left: none;
  border-radius: 0 6px 6px 0;
}

.regex-input {
  flex: 1;
  padding: 10px;
  border: 1px solid #ddd;
  border-left: none;
  border-right: none;
  font-family: 'Courier New', monospace;
  font-size: 20px;
  outline: none;
  transition: border-color 0.3s;
}

.regex-input:focus {
  border-color: #8e2de2;
}

.regex-input.error {
  border-color: #e74c3c;
}

/* 标志位选择样式 */
.flags-section {
  margin-bottom: 15px;
}

.flags-section h3 {
  font-size: 22px;
  color: #666;
  margin-bottom: 10px;
}

.flags-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px;
}

.flag-checkbox {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  padding: 8px;
  border-radius: 4px;
  transition: background 0.3s;
}

.flag-checkbox:hover {
  background: #f5f5f5;
}

.flag-input {
  display: none;
}

.flag-label {
  display: flex;
  align-items: center;
  gap: 8px;
}

.flag-char {
  width: 24px;
  height: 24px;
  background: #8e2de2;
  color: white;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  font-size: 16px;
}

.flag-desc {
  font-size: 18px;
  color: #666;
}

.flag-input:checked + .flag-label .flag-char {
  background: #4a00e0;
}

/* 测试文本区域 */
.test-textarea {
  width: 100%;
  min-height: 120px;
  padding: 15px;
  border: 1px solid #ddd;
  border-radius: 6px;
  font-family: 'Courier New', monospace;
  font-size: 18px;
  resize: vertical;
  outline: none;
  transition: border-color 0.3s;
}

.test-textarea:focus {
  border-color: #8e2de2;
}

/* 结果区域样式 */
.results-container {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.stats-card {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 15px;
  background: #f8f9fa;
  padding: 15px;
  border-radius: 8px;
}

.stat-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
}

.stat-label {
  font-size: 16px;
  color: #666;
  text-transform: uppercase;
}

.stat-value {
  font-size: 22px;
  font-weight: bold;
  color: #333;
}

.stat-value.success {
  color: #27ae60;
}

.stat-value.error {
  color: #e74c3c;
}

.matches-container h3,
.highlight-container h3 {
  font-size: 20px;
  color: #333;
  margin-bottom: 10px;
}

.matches-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.match-item {
  border: 1px solid #e0e0e0;
  border-radius: 6px;
  padding: 12px;
  background: #fafafa;
}

.match-header {
  display: flex;
  gap: 15px;
  margin-bottom: 8px;
  font-size: 16px;
  color: #666;
}

.match-index {
  font-weight: bold;
  color: #8e2de2;
}

.match-content {
  font-family: 'Courier New', monospace;
  background: white;
  padding: 8px;
  border-radius: 4px;
  border-left: 3px solid #8e2de2;
}

.match-groups {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed #ddd;
}

.group-item {
  display: flex;
  gap: 10px;
  padding: 4px 0;
  font-size: 16px;
}

.group-name {
  color: #8e2de2;
  font-weight: bold;
  min-width: 60px;
}

.group-content {
  font-family: 'Courier New', monospace;
  background: #f0f0f0;
  padding: 2px 6px;
  border-radius: 3px;
}

.no-matches {
  text-align: center;
  padding: 40px;
  color: #666;
}

.no-matches .icon {
  font-size: 48px;
  margin-bottom: 10px;
}

.highlighted-text {
  background: white;
  border: 1px solid #e0e0e0;
  border-radius: 6px;
  padding: 15px;
  font-family: 'Courier New', monospace;
  line-height: 1.5;
  white-space: pre-wrap;
}

.highlight {
  background: #fff3cd;
  padding: 2px 4px;
  border-radius: 3px;
  border: 1px solid #ffeaa7;
}

/* 常用模式库 */
.patterns-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 15px;
}

.pattern-card {
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  padding: 15px;
  cursor: pointer;
  transition: all 0.3s ease;
  background: white;
}

.pattern-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  border-color: #8e2de2;
}

.pattern-name {
  font-weight: bold;
  color: #333;
  margin-bottom: 8px;
}

.pattern-regex {
  font-family: 'Courier New', monospace;
  background: #f8f9fa;
  padding: 8px;
  border-radius: 4px;
  font-size: 16px;
  margin-bottom: 8px;
  word-break: break-all;
}

.pattern-desc {
  font-size: 16px;
  color: #666;
  line-height: 1.4;
}

footer {
  text-align: center;
  padding: 15px;
  background-color: #f5f5f5;
  color: #666;
  font-size: 18px;
}

.icon {
  font-style: normal;
}

.error-message {
  padding: 10px;
  background-color: #ffeaea;
  border-left: 4px solid #e74c3c;
  color: #c0392b;
  border-radius: 4px;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .section-title {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }

  .button-group {
    width: 100%;
    justify-content: flex-end;
  }

  .flags-grid {
    grid-template-columns: 1fr;
  }

  .stats-card {
    grid-template-columns: 1fr;
  }

  .patterns-grid {
    grid-template-columns: 1fr;
  }

  .match-header {
    flex-direction: column;
    gap: 5px;
  }
}
</style>